﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;


/************************************************************************************************************
* author 	:  YLH-PC
* function	:  
* history	:  created by YLH-PC 12/19/2014 1:46:51 PM 
************************************************************************************************************/
namespace Infrastructure.Lib.Core
{
    public static class LinqExtensions
    {
        /// <summary>
        /// 对 System.Collections.Generic.IEnumerable<T> 的每个元素执行指定操作。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumeration"></param>
        /// <param name="action">要对 System.Collections.Generic.IEnumerable<T> 的每个元素执行的 System.Action<T,T> 委托, 其中第一个参数为上一个元素, 第二个参数为当前元素</param>
        /// <summary>
        ///     Enumerates for each in this collection.
        /// </summary>
        /// <typeparam name="T">Generic type parameter.</typeparam>
        /// <param name="this">The @this to act on.</param>
        /// <param name="action">The action.</param>
        /// <returns>An enumerator that allows foreach to be used to process for each in this collection.</returns>
        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> @this, Action<T> action)
        {
            foreach (T t in @this)
            {
                action(t);
            }
            return @this;
        }

        /// <summary>
        /// 对 System.Collections.Generic.IEnumerable<T> 的每个元素执行指定操作。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumeration"></param>
        /// <param name="action">要对 System.Collections.Generic.IEnumerable<T> 的每个元素执行的 System.Action<int,T> 委托, 其中第一个参数为元素下标, 第二个参数为当前元素</param>
        public static void ForIndexEach<T>(this IEnumerable<T> enumeration, Action<int, T> action)
        {
            int index = 0;
            foreach (T item in enumeration)
            {
                action(index++, item);
            }
        }

        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Expression<Func<T, bool>> predicate)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, bool condition, Expression<Func<T, int, bool>> predicate)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, bool condition, Func<T, bool> predicate)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, bool condition, Func<T, int, bool> predicate)
        {
            return condition ? source.Where(predicate) : source;
        }
        public static bool IsBetween<T>(
            this T t, T lowerBound, T upperBound,
            bool includeLowerBound = false, bool includeUpperBound = false)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 映射连接
        /// </summary>
        /// <typeparam name="TOuter"></typeparam>
        /// <typeparam name="TInner"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="source"></param>
        /// <param name="inner">待连接集合</param>
        /// <param name="mapperFunc">映射方法</param>
        /// <returns>连接结果</returns>
        public static IEnumerable<TResult> MapperJoin<TOuter, TInner, TResult>(
            this IEnumerable<TOuter> source,
            IEnumerable<TInner> inner,
            Func<TOuter, TInner, TResult> mapperFunc)
        {
            List<TResult> result = new List<TResult>();
            foreach (var outer in source)
            {
                foreach (var innerItem in inner)
                {
                    var item = mapperFunc(outer, innerItem);
                    if (item != null)
                        result.Add(item);
                }
            }
            return result;
        }

        /// <summary>
        ///     An ICollection&lt;T&gt; extension method that adds a range to 'values'.
        /// </summary>
        /// <typeparam name="T">Generic type parameter.</typeparam>
        /// <param name="this">The @this to act on.</param>
        /// <param name="values">A variable-length parameters list containing values.</param>
        public static void AddRange<T>(this ICollection<T> @this, params T[] values)
        {
            foreach (T value in values)
            {
                @this.Add(value);
            }
        }
    }
}
